﻿using System.Collections.Generic;
using Microsoft.Practices.Unity;
using System;

namespace RefLib.IOC
{
    public sealed class SingletonContainer
    {
        public static IUnityContainer Get(bool buildNewContainer = false)
        {
            lock (_syncObject)
            {
                if (buildNewContainer && _container != null)
                {
                    _container.Dispose();
                    _container = null;
                }

                if (_container == null)
                {
                    _container = new UnityContainer();
                    foreach (UnityContainerExtension extension in _extensions.Values)
                    {
                        _container.AddExtension(extension);
                    }
                }
                
                return _container;
            }
        }

        public static void RegisterExtension(string extensionName, UnityContainerExtension extension)
        {
            lock (_syncObject)
            {
                if (_extensions.ContainsKey(extensionName))
                    _extensions[extensionName] = extension;
                else
                    _extensions.Add(extensionName, extension);
            }
        }

        public static void Release()
        {
            if (_container != null)
            {
                lock (_syncObject)
                {
                    if (_container != null)
                    {
                        _container.Dispose();
                        _container = null;
                    }
                }
            }
        }

        public static T Resolve<T>(Type targetType)
        {
            try
            {
                return (T) Get().Resolve(targetType);
            }
            catch
            {
                return (T) Get(true).Resolve(targetType);
            }
        }

        private SingletonContainer() { }

        private static IUnityContainer _container;
        private static Dictionary<string, UnityContainerExtension> _extensions = new Dictionary<string, UnityContainerExtension>();
        private static object _syncObject = new object();
    }
}
